package JUC;

/**
 * @author 豆包LU
 * @date 2023/5/8 17:47
 */
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class ToyFactory {
    private static final int TOY_MAX_COUNT = 100;
    private static final int WORKER_NUM = 2;
    private static final int CHILD_NUM = 3;
    private static final int PRODUCE_SPEED = 2;
    private static final int CONSUME_SPEED = 1;

    public static void main(String[] args) throws InterruptedException {
        // 创建阻塞队列
        ArrayBlockingQueue<Toy> toyQueue = new ArrayBlockingQueue<>(TOY_MAX_COUNT);

        // 创建线程池
        ExecutorService executorService = Executors.newFixedThreadPool(WORKER_NUM + CHILD_NUM);

        // 创建生产者
        for (int i = 0; i < WORKER_NUM; i++) {
            executorService.execute(new Worker("Worker" + (i + 1), toyQueue, PRODUCE_SPEED));
        }

        // 创建消费者
        for (int i = 0; i < CHILD_NUM; i++) {
            executorService.execute(new Child("Child" + (i + 1), toyQueue, CONSUME_SPEED));
        }

        // 等待6秒
        TimeUnit.SECONDS.sleep(3);

        // 停止生产
        executorService.shutdownNow();
        executorService.awaitTermination(1, TimeUnit.SECONDS);
        System.out.println("工人们停止生产玩具！");

        // 等待3秒
        TimeUnit.SECONDS.sleep(2);

        // 停止购买
        for (int i = 0; i < CHILD_NUM; i++) {
            toyQueue.put(Toy.STOP);
        }
        System.out.println("小孩们停止购买玩具！");

        // 等待线程池中所有线程执行完毕
        executorService.awaitTermination(1, TimeUnit.SECONDS);
        System.out.println("玩具生产结束，小孩们离开了玩具店！");
    }

    private static class Worker implements Runnable {
        private final String name;
        private final ArrayBlockingQueue<Toy> toyQueue;
        private final int produceSpeed;

        public Worker(String name, ArrayBlockingQueue<Toy> toyQueue, int produceSpeed) {
            this.name = name;
            this.toyQueue = toyQueue;
            this.produceSpeed = produceSpeed;
        }

        @Override
        public void run() {
            try {
                while (!Thread.interrupted()) {
                    Toy toy = new Toy(name);
                    toyQueue.put(toy);
                    System.out.println(name + "生产了" + toy.getName());
                    TimeUnit.MILLISECONDS.sleep(1000 / produceSpeed);
                }
            } catch (InterruptedException e) {
                System.out.println(name + "停止了生产");
            }
        }
    }

    private static class Child implements Runnable {
        private final String name;
        private final ArrayBlockingQueue<Toy> toyQueue;
        private final int consumeSpeed;

        public Child(String name,ArrayBlockingQueue<Toy> toyQueue, int consumeSpeed) {
            this.name = name;
            this.toyQueue = toyQueue;
            this.consumeSpeed = consumeSpeed;
        }

        @Override
        public void run() {
            try {
                while (true) {
                    Toy toy = toyQueue.take();
                    if (toy == Toy.STOP) {
                        break;
                    }
                    System.out.println(name + "购买了" + toy.getName());
                    TimeUnit.MILLISECONDS.sleep(1000 / consumeSpeed);
                }
            } catch (InterruptedException e) {
                System.out.println(name + "停止了购买");
            }
        }
    }

    private static class Toy {
        public static final Toy STOP = new Toy("STOP");
        private final String name;

        public Toy(String name) {
            this.name = name;
        }

        public String getName() {
            return name;
        }
    }
}

